package com.yonyou.pmclouds.statistic.service.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.DateUtils;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import com.yonyou.pmclouds.signin.mapper.SignInStatisticMapper;
import com.yonyou.pmclouds.statistic.entity.SignInListReportVO;
import com.yonyou.pmclouds.statistic.entity.SignInListReportViewVO;
import com.yonyou.pmclouds.statistic.entity.SignInQueryRecordVO;
import com.yonyou.pmclouds.statistic.entity.SignInUserReportVO;
import com.yonyou.pmclouds.statistic.rmiitf.SignInStatisticService;
import com.yonyou.pmclouds.team.entity.TeamMemberVO;
import com.yonyou.pmclouds.team.rmiitf.TeamMemberQuery;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 签到报表查询实现类
 *
 * @author th
 * @date 2019/7/20 11:07
 */
@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = SignInStatisticService.class, timeout = 5000)
public class SignInStatisticServiceImpl implements SignInStatisticService {

    @Autowired
    private ProjectSimpleQuery projectSimpleQuery;
    @Autowired
    private SignInStatisticMapper mapper;
    @Autowired
    private TeamMemberQuery teamMemberQuery;

    @Override
    public List<SignInListReportViewVO> queryListOfProjects(String tenantId, String[] orgIds, String[] projectIds,
                                                            long timeStart, long timeEnd) throws BusinessException {
        if (ArrayUtils.isEmpty(projectIds))
            projectIds = getProjectIdsByOrgs(tenantId, orgIds);
        if (ArrayUtils.isEmpty(projectIds))
            return new ArrayList<>();
        Date startDate = DateUtils.asDateBegin(new Date(timeStart));
        Date endDate = DateUtils.asDateEnd(new Date(timeEnd));
        // 查到项目有关的所有签到记录
        List<SignInQueryRecordVO> signInQueryRecordVOList = mapper.queryAllRecordsOfProjects(tenantId, projectIds, startDate, endDate);
        List<SignInListReportViewVO> viewVOList = groupByProjectOrEnter(signInQueryRecordVOList, SignInListReportViewVO.PK_PROJECT);
        Set<String> pkProjects = new HashSet<>();
        for (SignInListReportViewVO vo : viewVOList) {
            pkProjects.add(vo.getPkProject());
        }
        // 补充没有做过签到的项目
        if (ArrayUtils.isEmpty(projectIds))
            return new ArrayList<>();
        List<SignInListReportViewVO> results = new ArrayList<>();
        for (String pkProject : projectIds) {
            if (pkProjects.contains(pkProject))
                continue;
            SignInListReportViewVO viewVO = new SignInListReportViewVO();
            viewVO.setViewId(pkProject);
            viewVO.setPkProject(pkProject);
            List<SignInListReportVO> reportVOS = new ArrayList<>();
            addNoSignInMember(reportVOS, null, pkProject, SignInListReportViewVO.PK_PROJECT);
            viewVO.setReportVO(reportVOS);
            results.add(viewVO);
        }
        setProjectCodeAndName(results);
        viewVOList.addAll(results);
        Collections.sort(viewVOList, new ReportOfProjectComparator());

        return viewVOList;
    }

    @Override
    public List<SignInUserReportVO> queryUserSignInOfProject(String tenantId, String userId, String projectId,
                                                             long timeStart, long timeEnd) throws BusinessException {
        if (StringUtils.isEmpty(projectId))
            return new ArrayList<>();
        Date startDate = DateUtils.asDateBegin(new Date(timeStart));
        Date endDate = DateUtils.asDateEnd(new Date(timeEnd));
        // 查询用户的所有签到记录
        List<SignInQueryRecordVO> signInQueryRecordVOList = mapper.queryUserSignInOfProject(tenantId, userId, projectId, startDate, endDate);
        List<SignInUserReportVO> results = getUserSignInDetailsOfProjectOrEnt(signInQueryRecordVOList, SignInListReportViewVO.PK_PROJECT);

        return results;
    }

    @Override
    public List<SignInUserReportVO> queryUserSignInOfEnt(String tenantId, String[] orgIds, String enterpriseId, String userId, long timeStart, long timeEnd) throws BusinessException {
        String[] projectIds = getProjectIdsByOrgs(tenantId, orgIds);
        if (ArrayUtils.isEmpty(projectIds))
            return new ArrayList<>();
        Date startDate = DateUtils.asDateBegin(new Date(timeStart));
        Date endDate = DateUtils.asDateEnd(new Date(timeEnd));

        List<SignInQueryRecordVO> userSignInRecords = mapper.queryUserSignInOfEnt(tenantId, userId, enterpriseId, projectIds, startDate, endDate);
        List<SignInUserReportVO> results = getUserSignInDetailsOfProjectOrEnt(userSignInRecords, SignInListReportViewVO.PK_ENTERPRISE);

        return results;
    }

    @Override
    public List<SignInListReportViewVO> queryListOfEnterprises(String tenantId, String[] orgIds, long timeStart, long timeEnd) throws BusinessException {
        String[] projectIds = getProjectIdsByOrgs(tenantId, orgIds);
        if (ArrayUtils.isEmpty(projectIds))
            return new ArrayList<>();
        Date startDate = DateUtils.asDateBegin(new Date(timeStart));
        Date endDate = DateUtils.asDateEnd(new Date(timeEnd));
        // 查到项目有关的所有签到记录
        List<SignInQueryRecordVO> allRecords = mapper.queryAllRecordsOfProjects(tenantId, projectIds, startDate, endDate);
        List<SignInListReportViewVO> enterpriseList = groupByProjectOrEnter(allRecords, SignInListReportViewVO.PK_ENTERPRISE);
        // 补全无签到记录的企业
        if (ArrayUtils.isEmpty(projectIds)) {
            return new ArrayList<>();
        }
        TeamMemberVO[] memberVOS = teamMemberQuery.queryByprojects(projectIds);
        if (ArrayUtils.isEmpty(memberVOS))
            return enterpriseList;
        Set<String> signInEnts = new HashSet<>();
        for (SignInListReportViewVO viewVo : enterpriseList) {
            signInEnts.add(viewVo.getPkEnterprise());
        }
        List<String> entList = new ArrayList<>();
        for (TeamMemberVO memberVo : memberVOS) {
            String pkEnt = memberVo.getPkEnterprise();
            if (StringUtils.isNotEmpty(pkEnt) && !entList.contains(pkEnt) && !signInEnts.contains(pkEnt)) {
                entList.add(memberVo.getPkEnterprise());
                SignInListReportViewVO viewVO = new SignInListReportViewVO();
                viewVO.setViewId(pkEnt);
                viewVO.setPkEnterprise(pkEnt);
                List<SignInListReportVO> reportVOS = new ArrayList<>();
                addNoSignInMember(reportVOS, null, pkEnt, SignInListReportViewVO.PK_ENTERPRISE);
                viewVO.setReportVO(reportVOS);
                enterpriseList.add(viewVO);
            }
        }

        return enterpriseList;
    }

    /**
     * 通过租户和组织查询项目
     *
     * @param tenantId
     * @param orgIds
     * @return
     */
    private String[] getProjectIdsByOrgs(String tenantId, String[] orgIds) throws BusinessException {
        String[] projectIds;
        if (ArrayUtils.isNotEmpty(orgIds) && orgIds.length > 1) {
            projectIds = projectSimpleQuery.queryProjectIdsByOrgs(tenantId, orgIds);
        } else if (ArrayUtils.isNotEmpty(orgIds)) {
            projectIds = projectSimpleQuery.queryProjectIdByTenantOrg(null, tenantId, orgIds[0]);
        } else {
            projectIds = projectSimpleQuery.queryProjectIdByTenantOrg(null, tenantId, null);
        }

        return projectIds;
    }

    /**
     * 获得用户在项目或企业下的签到详情报表
     *
     * @param signInQueryRecordVOList
     * @return
     */
    private List<SignInUserReportVO> getUserSignInDetailsOfProjectOrEnt(List<SignInQueryRecordVO> signInQueryRecordVOList, String groupField) throws BusinessException {
        // <当天，当天的签到记录>
        Map<String, List<SignInQueryRecordVO>> dayStrToRecords = new HashMap<>();
        if (signInQueryRecordVOList == null || signInQueryRecordVOList.size() == 0)
            return new ArrayList<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String currDay;
        for (SignInQueryRecordVO record : signInQueryRecordVOList) {
            currDay = format.format(record.getCreationtime());
            if (!dayStrToRecords.containsKey(currDay)) {
                dayStrToRecords.put(currDay, new ArrayList<SignInQueryRecordVO>());
            }
            dayStrToRecords.get(currDay).add(record);
        }
        List<SignInUserReportVO> results = new ArrayList<>();
        // 企业下成员的签到统计，一天可能签到多个项目，需特殊处理
        if (SignInListReportViewVO.PK_ENTERPRISE.equals(groupField)) {
            results = getDaySignInOfProjects(dayStrToRecords);
            // 设置项目名
            setProjectNames(results);
        } else {
            for (String dayStr : dayStrToRecords.keySet()) {
                SignInUserReportVO userReportVO = new SignInUserReportVO();
                userReportVO.setDay(dayStr);
                // 设置当天最早、最晚签到时间、位置和时长
                setSignInDayDetails(userReportVO, dayStrToRecords.get(dayStr));
                results.add(userReportVO);
            }
        }

        // 按日期排序
        Collections.sort(results, new SignInDateComparator());

        return results;
    }

    /**
     * 设置项目名
     *
     * @param results
     */
    private void setProjectNames(List<SignInUserReportVO> results) throws BusinessException {
        if (results == null || results.size() == 0)
            return;

        Set<String> projectIds = new HashSet<>();
        for (SignInUserReportVO vo : results) {
            if (StringUtils.isNotEmpty(vo.getPkProject()))
                projectIds.add(vo.getPkProject());
        }
        Map<String, String> pkToName = projectSimpleQuery.queryProjectNameByIds(projectIds.toArray(new String[projectIds.size()]));

        if (pkToName == null)
            return;

        for (SignInUserReportVO vo : results) {
            if (StringUtils.isNotEmpty(vo.getPkProject()))
                vo.setProjectName(pkToName.get(vo.getPkProject()));
        }
    }

    /**
     * 企业下成员的签到统计，一天可能签到多个项目，需特殊处理
     *
     * @param dayStrToRecords
     * @return
     */
    private List<SignInUserReportVO> getDaySignInOfProjects(Map<String, List<SignInQueryRecordVO>> dayStrToRecords) {
        List<SignInUserReportVO> results = new ArrayList<>();
        if (dayStrToRecords == null || dayStrToRecords.size() == 0)
            return results;
        List<SignInQueryRecordVO> dayRecords;

        String pkProject;
        for (String dayStr : dayStrToRecords.keySet()) {
            // <项目，当天项目的签到记录>
            Map<String, List<SignInQueryRecordVO>> projectToRecords = new HashMap<>();
            dayRecords = dayStrToRecords.get(dayStr);
            for (SignInQueryRecordVO record : dayRecords) {
                pkProject = record.getPkProject();
                if (StringUtils.isNotEmpty(pkProject)) {
                    if (!projectToRecords.containsKey(pkProject))
                        projectToRecords.put(pkProject, new ArrayList<SignInQueryRecordVO>());
                    projectToRecords.get(pkProject).add(record);
                }
            }
            if (projectToRecords.size() > 0) {
                for (String projectId : projectToRecords.keySet()) {
                    SignInUserReportVO reportVO = new SignInUserReportVO();
                    reportVO.setDay(dayStr);
                    reportVO.setPkProject(projectId);
                    // 设置当天最早、最晚签到时间、位置和时长
                    setSignInDayDetails(reportVO, projectToRecords.get(projectId));
                    results.add(reportVO);
                }
            }
        }

        return results;
    }

    /**
     * 获取当天最早、最晚签到时间、位置和时长
     *
     * @param userReportVO
     * @param signInQueryRecordVOS
     */
    private void setSignInDayDetails(SignInUserReportVO userReportVO, List<SignInQueryRecordVO> signInQueryRecordVOS) {
        if (signInQueryRecordVOS == null || signInQueryRecordVOS.size() == 0)
            return;
        Date earliestTime = signInQueryRecordVOS.get(0).getCreationtime();
        Date latestTime = signInQueryRecordVOS.get(0).getCreationtime();
        Date currTime;
        String earlyPositon = signInQueryRecordVOS.get(0).getPosition();
        String latePostion = signInQueryRecordVOS.get(0).getPosition();
        String sumHours = null;
        SignInQueryRecordVO currRecord;
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        // 只有一条签到记录
        if (signInQueryRecordVOS.size() == 1) {
            currTime = signInQueryRecordVOS.get(0).getCreationtime();
            StringBuffer timeAndPostion = new StringBuffer();
            timeAndPostion.append(format.format(currTime));
            timeAndPostion.append(" ");
            timeAndPostion.append(earlyPositon);
            userReportVO.setEarliestAndPos(timeAndPostion.toString());
            userReportVO.setHours(sumHours);
            return;
        }
        Map<String, List<SignInQueryRecordVO>> dayToTimes = new HashMap<>();
        String dayStr = userReportVO.getDay();
        dayToTimes.put(dayStr, new ArrayList<SignInQueryRecordVO>());
        dayToTimes.get(dayStr).add(signInQueryRecordVOS.get(0));
        // 获取最早、最晚签到时间和位置
        for (int i = 1; i < signInQueryRecordVOS.size(); i++) {
            currTime = signInQueryRecordVOS.get(i).getCreationtime();
            currRecord = signInQueryRecordVOS.get(i);
            if (currTime.before(earliestTime)) {
                earliestTime = currTime;
                earlyPositon = signInQueryRecordVOS.get(i).getPosition();
            }
            if (currTime.after(latestTime)) {
                latestTime = currTime;
                latePostion = signInQueryRecordVOS.get(i).getPosition();
            }
            dayToTimes.get(dayStr).add(currRecord);
        }
        StringBuffer sb = new StringBuffer();
        sb.append(format.format(earliestTime));
        sb.append(" ");
        sb.append(earlyPositon);
        userReportVO.setEarliestAndPos(sb.toString());

        sb.setLength(0);
        sb.append(format.format(latestTime));
        sb.append(" ");
        sb.append(latePostion);
        userReportVO.setLatestAndPos(sb.toString());

        // 计算时长
        sumHours = calcTotalHoursOfUser(dayToTimes);
        userReportVO.setHours(sumHours);
    }

    /**
     * 根据项目或企业进行分组，统计项目或企业成员的签到情况
     *
     * @param signInQueryRecordVOList
     * @return
     */
    private List<SignInListReportViewVO> groupByProjectOrEnter(List<SignInQueryRecordVO> signInQueryRecordVOList, String groupField) throws BusinessException {
        List<SignInListReportViewVO> results = new ArrayList<>();
        if (signInQueryRecordVOList == null || signInQueryRecordVOList.size() == 0)
            return results;
        Map<String, List<SignInQueryRecordVO>> pkToReportRecords = new HashMap<>();
        for (SignInQueryRecordVO recordVO : signInQueryRecordVOList) {
            if (groupField.equals(SignInListReportViewVO.PK_PROJECT)) {
                if (StringUtils.isEmpty(recordVO.getPkProject()))
                    continue;
                if (!pkToReportRecords.containsKey(recordVO.getPkProject())) {
                    pkToReportRecords.put(recordVO.getPkProject(), new ArrayList<SignInQueryRecordVO>());
                }
                pkToReportRecords.get(recordVO.getPkProject()).add(recordVO);
            } else {
                if (StringUtils.isEmpty(recordVO.getPkEnterprise()))
                    continue;
                if (!pkToReportRecords.containsKey(recordVO.getPkEnterprise())) {
                    pkToReportRecords.put(recordVO.getPkEnterprise(), new ArrayList<SignInQueryRecordVO>());
                }
                pkToReportRecords.get(recordVO.getPkEnterprise()).add(recordVO);
            }
        }
        for (String pk : pkToReportRecords.keySet()) {
            SignInListReportViewVO listReportViewVO = getSignInListViewOfProjectOrEnt(pkToReportRecords.get(pk), groupField);
            if (groupField.equals(SignInListReportViewVO.PK_PROJECT)) {
                listReportViewVO.setPkProject(pk);
                listReportViewVO.setViewId(pk);
            } else {
                listReportViewVO.setPkEnterprise(pk);
                listReportViewVO.setViewId(pk);
            }
            results.add(listReportViewVO);
        }
        // 设置项目编码、名称
        if (groupField.equals(SignInListReportViewVO.PK_PROJECT)) {
            setProjectCodeAndName(results);
        }

        return results;
    }

    /**
     * 设置项目编码和项目名
     *
     * @param results
     */
    private void setProjectCodeAndName(List<SignInListReportViewVO> results) throws BusinessException {
        if (results == null || results.size() == 0)
            return;
        Set<String> projectIds = new HashSet<>();
        for (SignInListReportViewVO vo : results) {
            projectIds.add(vo.getPkProject());
        }
        Map<String, ProjectVO> idToVo = projectSimpleQuery.queryProjects(projectIds.toArray(new String[projectIds.size()]));
        List<SignInListReportVO> reportVOS;
        // 给列表中的项目pk、项目编码、项目名赋值
        for (SignInListReportViewVO vo : results) {
            String pkProject = vo.getPkProject();
            vo.setProjectName(idToVo.get(pkProject).getSname());
            vo.setProjectCode(idToVo.get(pkProject).getScode());
            reportVOS = vo.getReportVO();
            if (reportVOS != null && reportVOS.size() > 0) {
                for (SignInListReportVO reportVO : reportVOS) {
                    if (StringUtils.isEmpty(reportVO.getPkProject()))
                        reportVO.setPkProject(pkProject);
                    reportVO.setProjectName(idToVo.get(pkProject).getSname());
                }
            }
        }
    }

    /**
     * 统计该项目或企业下成员的签到情况
     *
     * @param signInQueryRecordVOS
     * @return
     */
    private SignInListReportViewVO getSignInListViewOfProjectOrEnt(List<SignInQueryRecordVO> signInQueryRecordVOS, String groupField) throws BusinessException {
        SignInListReportViewVO listReportViewVO = new SignInListReportViewVO();
        if (signInQueryRecordVOS == null || signInQueryRecordVOS.size() == 0)
            return listReportViewVO;
        // <成员，签到记录>
        Map<String, List<SignInQueryRecordVO>> userToRecords = new HashMap<>();
        for (SignInQueryRecordVO record : signInQueryRecordVOS) {
            if (!userToRecords.containsKey(record.getPkUser()))
                userToRecords.put(record.getPkUser(), new ArrayList<SignInQueryRecordVO>());
            userToRecords.get(record.getPkUser()).add(record);
        }
        // 项目或企业下的成员签到情况
        List<SignInListReportVO> listReportVOList = new ArrayList<>();
        for (String pkUser : userToRecords.keySet()) {
            SignInListReportVO reportVO = getUserReportOfProjectOrEnt(userToRecords.get(pkUser), groupField);
            listReportVOList.add(reportVO);
        }
        // 补全在项目或企业下没有签到的成员
        if (SignInListReportViewVO.PK_ENTERPRISE.equals(groupField)) {
            addNoSignInMember(listReportVOList, userToRecords.keySet(), signInQueryRecordVOS.get(0).getPkEnterprise(), groupField);
        } else {
            addNoSignInMember(listReportVOList, userToRecords.keySet(), signInQueryRecordVOS.get(0).getPkProject(), groupField);
        }
        // 排序
        Collections.sort(listReportVOList, new ReportOfUserComparator());
        listReportViewVO.setReportVO(listReportVOList);

        return listReportViewVO;
    }

    /**
     * 补全项目或企业下没有签到的成员
     *
     * @param listReportVOList
     * @param keySet
     * @param pk
     * @param groupField
     */
    private void addNoSignInMember(List<SignInListReportVO> listReportVOList, Set<String> keySet, String pk, String groupField) throws BusinessException {
        if (StringUtils.isEmpty(pk))
            return;
        // 未签到的成员
        List<TeamMemberVO> userList = new ArrayList<>();
        TeamMemberVO[] allUsers;

        if (SignInListReportViewVO.PK_PROJECT.equals(groupField)) {
            allUsers = teamMemberQuery.queryByProject(pk);
        } else {
            allUsers = teamMemberQuery.queryByEnterprise(RuntimeEnvironment.getTenantId(), pk);
        }

        if (ArrayUtils.isEmpty(allUsers))
            return;

        for (TeamMemberVO user : allUsers) {
            if (keySet == null || (keySet != null && !keySet.contains(user.getPkUser()))) {
                userList.add(user);
            }
        }

        if (userList.size() == 0)
            return;

        // 记录本次生成签到记录的用户pk
        List<String> userIds = new ArrayList<>();
        for (TeamMemberVO user : userList) {
            if (StringUtils.isEmpty(user.getPkUser()))
                return;
            if (userIds.contains(user.getPkUser()))
                continue;
            userIds.add(user.getPkUser());
            SignInListReportVO reportVO = new SignInListReportVO();
            reportVO.setPkUser(user.getPkUser());
            reportVO.setSignInDays(0);
            reportVO.setTotalHours("0");
            reportVO.setViewId(pk);
            if (SignInListReportViewVO.PK_PROJECT.equals(groupField)) {
                reportVO.setPkProject(pk);
                reportVO.setPkEnterprise(user.getPkEnterprise());
            } else {
                reportVO.setPkEnterprise(pk);
            }
            listReportVOList.add(reportVO);
        }
    }

    /**
     * 统计某个成员的签到情况
     *
     * @param signInQueryRecordVOS
     * @return
     */
    private SignInListReportVO getUserReportOfProjectOrEnt(List<SignInQueryRecordVO> signInQueryRecordVOS, String groupField) {
        SignInListReportVO reportVO = new SignInListReportVO();
        if (signInQueryRecordVOS == null || signInQueryRecordVOS.size() == 0)
            return reportVO;
        // 签到天数
        Integer days = 0;
        Date currDate;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        List<String> dateStrs = new ArrayList<>();
        String dateStr;
        // <当天日期，当天用户所有签到时间>
        Map<String, List<SignInQueryRecordVO>> dayMap = new HashMap<>();
        for (SignInQueryRecordVO record : signInQueryRecordVOS) {
            currDate = record.getCreationtime();
            dateStr = format.format(currDate);
            // 计算签到天数
            if (!dateStrs.contains(dateStr)) {
                dateStrs.add(dateStr);
                days++;
            }
            if (!dayMap.containsKey(dateStr))
                dayMap.put(dateStr, new ArrayList<SignInQueryRecordVO>());
            dayMap.get(dateStr).add(record);
        }
        // 计算签到总时长
        String hours = calcTotalHoursOfUser(dayMap);
        reportVO.setSignInDays(days);
        reportVO.setTotalHours(hours);
        reportVO.setPkUser(signInQueryRecordVOS.get(0).getPkUser());
        // 按项目维度统计，需要设置企业、用户角色、项目、主表pk
        if (SignInListReportViewVO.PK_PROJECT.equals(groupField)) {
            reportVO.setPkEnterprise(signInQueryRecordVOS.get(0).getPkEnterprise());
            reportVO.setUserRole(signInQueryRecordVOS.get(0).getUserRole());
            reportVO.setPkProject(signInQueryRecordVOS.get(0).getPkProject());
            reportVO.setViewId(signInQueryRecordVOS.get(0).getPkProject());
        } else {
            // 企业维度，设置企业pk、主表pk
            reportVO.setPkEnterprise(signInQueryRecordVOS.get(0).getPkEnterprise());
            reportVO.setViewId(signInQueryRecordVOS.get(0).getPkEnterprise());
        }

        return reportVO;
    }

    /**
     * 计算用户签到总时长
     *
     * @param dayMap
     * @return
     */
    private String calcTotalHoursOfUser(Map<String, List<SignInQueryRecordVO>> dayMap) {
        String hours = "0";
        if (dayMap == null || dayMap.size() == 0)
            return hours;
        long currDayTime;
        long sumHours = 0;
        long sumMins = 0;
        long nh = 1000 * 60 * 60; //一小时的毫秒数
        long nm = 1000 * 60; //一分钟的毫秒数
        Date earliestDate;
        Date latestDate;
        Date currDate;
        List<SignInQueryRecordVO> dayRecords;

        for (String dayStr : dayMap.keySet()) {
            dayRecords = dayMap.get(dayStr);
            // 每天至少两次签到，才有效
            if (dayRecords == null || dayRecords.size() < 2)
                continue;
            // <项目，项目上签到记录>
            Map<String, List<SignInQueryRecordVO>> projectToRecords = new HashMap<>();
            for (SignInQueryRecordVO vo : dayRecords) {
                String pkPro = vo.getPkProject();
                if (!projectToRecords.containsKey(pkPro))
                    projectToRecords.put(pkPro, new ArrayList<SignInQueryRecordVO>());
                projectToRecords.get(pkPro).add(vo);
            }
            for (String pkProject : projectToRecords.keySet()) {
                List<SignInQueryRecordVO> projectRecords = projectToRecords.get(pkProject);
                if (projectRecords == null || projectRecords.size() < 2)
                    continue;
                earliestDate = projectRecords.get(0).getCreationtime();
                latestDate = projectRecords.get(0).getCreationtime();
                for (int i = 1; i < projectRecords.size(); i++) {
                    currDate = projectRecords.get(i).getCreationtime();
                    if (currDate.before(earliestDate))
                        earliestDate = currDate;
                    if (currDate.after(latestDate))
                        latestDate = currDate;
                }
                // 计算当天时长(以微秒为单位)
                currDayTime = latestDate.getTime() - earliestDate.getTime();
                // 小时数
                sumHours += currDayTime / nh;
                // 分钟数
                sumMins += currDayTime % nh / nm;
            }
        }
        if (sumMins >= 60) {
            sumHours += sumMins / 60;
            sumMins = sumMins % 60;
        }
        // 返回小时+分钟
        if (sumHours < 1) {
            if (sumMins < 1)
                return "0";
            hours = sumMins + "分";
        } else if (sumHours >= 1 && sumMins == 0) {
            hours = sumHours + "小时";
        } else {
            hours = sumHours + "小时" + sumMins + "分";
        }

        return hours;
    }

    /**
     * 项目、企业下成员按签到天数倒序
     */
    public static class ReportOfUserComparator implements Comparator<SignInListReportVO> {

        @Override
        public int compare(SignInListReportVO o1, SignInListReportVO o2) {
            if (o1.getSignInDays() == null && o2.getSignInDays() != null) {
                return 1;
            } else if (o1.getSignInDays() != null && o2.getSignInDays() == null) {
                return -1;
            } else if (o1.getSignInDays() != null && o2.getSignInDays() != null) {
                if (o1.getSignInDays() > o2.getSignInDays()) {
                    return -1;
                } else {
                    return 1;
                }
            }

            return 0;
        }
    }

    /**
     * 项目按编码排序
     */
    public static class ReportOfProjectComparator implements Comparator<SignInListReportViewVO> {

        @Override
        public int compare(SignInListReportViewVO o1, SignInListReportViewVO o2) {
            return o1.getProjectCode().compareTo(o2.getProjectCode());
        }
    }

    /**
     * 签到日期倒序
     */
    public static class SignInDateComparator implements Comparator<SignInUserReportVO> {

        @Override
        public int compare(SignInUserReportVO o1, SignInUserReportVO o2) {
            if (o1.getDay() == null && o2 != null) {
                return 1;
            } else if (o1.getDay() != null && o2.getDay() == null) {
                return -1;
            } else if (o1.getDay() != null && o2.getDay() != null) {
                if (o1.getDay().equals(o2.getDay()))
                    return 0;
                return o1.getDay().compareTo(o2.getDay());
            }

            return 0;
        }
    }


}
